import Bb from 'backbone';
import ExpenseModel from "./ExpenseModel.js";
import Radio from 'backbone.radio';
import { round } from '../../math.js';

const ExpenseCollection = Bb.Collection.extend({
    /*
     *  Collection of expense lines
     *
     * Maintains a special state in this.aggregates.justified :
     *  - true when all lines have justified=true
     *  - false when all lines have justified=false
     *  - null else
     *
     * That attribute can be watched for change with aggregate:change:justified
     */
    model: ExpenseModel,
    initialize(){
        this.on('destroyed', this.channelCall);
        this.on('saved', this.channelCall);
        this.on(
            'change:justified add remove reset',
            function(){
                this.updateAggregate('justified');
            }.bind(this),
        );
        this.aggregates = {};
    },
    channelCall: function(model){
        var channel = Radio.channel('facade');
        channel.trigger('changed:line');
    },
    updateAggregate(property) {
        let previousValue = this.aggregates[property];
        let newValue = this.computeAggregate(property);
        this.aggregates[property] = newValue;
        if (newValue !== previousValue) {
            this.trigger(`aggregate:change:${property}`, newValue);
        }
    },
    computeAggregate(property){
      let totalCount = this.models.length;
      let matchingCount = this.models.filter(x => (x.get(property))
      ).length;
      if (totalCount > 0) {
        if (totalCount === matchingCount) {
              return true;
          } else if (matchingCount === 0) {
              return false;
          } else {
            return null;  // mixed
        }
      } else {
          return null;
      }
    },
    url(){
        return AppOption['context_url'] + "/lines";
    },
    comparator: function( a, b ){
      /*
       * Sort the collection and place
       *   - unjustified lines at the begining
       *   - special lines at the end
       */
      var res = 0;

      if (b.get('justified') != a.get('justified')){
        // Unjustified goes first
        if ( ! b.get('justified')) {
          return  1;
        } else {
          res = -1;
        }
      } else if (a.isTelType() != b.isTelType()) {
          // Tel type goes last
          if (b.isTelType()){
            res = -1;
          } else {
            res = 1;
          }
      }else{
        var acat = a.get('category');
        var bcat = b.get('category');
        if ( acat < bcat ){
          res = -1;
        }else if ( acat > bcat ){
          res = 1;
        } else {
          var adate = a.get('altdate');
          var bdate = a.get('altdate');
          if (adate < bdate){
            res = -1;
          } else if ( acat > bcat ){
            res = 1;
          }
        }
      }
      return res;
    },
    total_ht: function(category){
      /*
       * Return the total value
       */
      var result = 0;
      this.each(function(model){
        if (category != undefined){
          if (model.get('category') != category){
            return;
          }
        }
        result += round(model.getHT());
      });
      return result;
    },
    total_tva: function(category){
      /*
       * Return the total value
       */
      var result = 0;
      this.each(function(model){
        if (category != undefined){
          if (model.get('category') != category){
            return;
          }
        }
        result += round(model.getTva());
      });
      return result;
    },
    total: function(category){
      /*
       * Return the total value
       */
      var result = 0;
      this.each(function(model){
        if (category != undefined){
          if (model.get('category') != category){
            return;
          }
        }
        result += round(model.total());
      });
      return result;
    },
    /**  Gathers the IDs of the files that are linked a line or more
     *
     * @returns {Set[int]} file ids that are linked to at least one expense
     *   line.
     */
    collectLinkedFileIds(){ // FIXME : et sur delete d'expense ?
        let fileIds = new Set();
        this.each(function(model){
            for (let id of model.get('files')) {
                // Force cast to int
                fileIds.add(parseInt(id, 10));
            }
        });
        return fileIds;
    },
});
export default ExpenseCollection;
